#!/usr/bin/env python

import os
import sys
import subprocess
import shutil
import filecmp
from misc import cmdln


class BaeTools(cmdln.Cmdln):
    name = "baetools"

    @cmdln.alias("pl")
    @cmdln.option("-u", "--url", type="string", dest="url",
                  help="specify Bae app SVN")
    @cmdln.option("-v", "--version", type="string", dest="version", default="",
                  help="specify Bae app version")
    @cmdln.option("-p", "--path", type="string", dest="path", default=".",
                  help="specify local path")
    @cmdln.option("", "--username", type="string", dest="uname",
                  help="specify svn repo username")
    @cmdln.option("", "--password", type="string", dest="passwd",
                  help="specify svn repo passwd")
    def do_pull(self, subcmd, opts, *args):
        """${cmd_name}: Download the Bae app repository 

        ${cmd_usage}
        ${cmd_option_list}
        """
        url = os.path.join(opts.url, opts.version)
        args = ["svn", "export", url, os.path.abspath(os.path.expanduser(opts.path))]
        if opts.uname is not None and opts.passwd is not None:
            args.extend(["--username", opts.uname, "--password", opts.passwd])
        subprocess.call(args)        
 
    @cmdln.alias("ps")
    @cmdln.option("-d", "--dir", type="string", dest="dir",
                  help="specify local source directory")
    @cmdln.option("-u", "--url", type="string", dest="url",
                  help="specify Bae app SVN")
    @cmdln.option("-v", "--version", type="string", dest="version", default="", 
                  help="specify Bae app version")
    @cmdln.option("", "--username", type="string", dest="uname",
                  help="specify svn repo username")
    @cmdln.option("", "--password", type="string", dest="passwd",
                  help="specify svn repo passwd")
    def do_push(self, subcmd, opts, *args):
        """${cmd_name}: Push local source to Bae

        ${cmd_usage}
        ${cmd_option_list}
        """
        dir = os.path.abspath(os.path.expanduser(opts.dir))
        if not os.path.exists(dir):
            print "please specify a valid dirname"
            sys.exit(-1)

        url = os.path.join(opts.url, opts.version)
        localsvn = os.path.abspath(os.path.expanduser("./.baelocal/"))
        localsvn = os.path.join(localsvn, os.path.basename(opts.url), opts.version)
        if not os.path.exists(localsvn):
            args = ["svn", "checkout", url, localsvn]
            if opts.uname is not None and opts.passwd is not None:
                args.extend(["--username", opts.uname, "--password", opts.passwd])
            subprocess.call(args)
        else:
            args = ["svn", "update", "-q", localsvn]
            if opts.uname is not None and opts.passwd is not None:
                args.extend(["--username", opts.uname, "--password", opts.passwd])
            subprocess.call(args)
        diffs = [{'a': localsvn,
                 'b': dir, 
                 'cmp': filecmp.dircmp(localsvn, dir, [".svn"])}]
                    
        _cp = lambda x: shutil.copytree if x else shutil.copy2

        while len(diffs):
            d = diffs.pop(0)
            a, b, cmp = d['a'], d['b'], d['cmp']
            
            for f in cmp.left_only:
                _f = os.path.join(a, f) 
                subprocess.call(["svn", "delete", "-q", _f])
            for f in cmp.right_only:
                _f = os.path.join(b, f)
                _cp(os.path.isdir(_f))(_f, os.path.join(a, f))
                subprocess.call(["svn", "add", "-q", os.path.join(a, f)])
            for f in cmp.diff_files:
                _f = os.path.join(b, f)
                _cp(0)(_f, os.path.join(a, f))    
            for k, v in cmp.subdirs.items():
                diffs.append({'a': os.path.join(a, k),
                              'b': os.path.join(b, k),
                              'cmp':  v})
            subprocess.call(['svn', 'commit', '-mx', localsvn])
        print 'Deployed in Bae'

if __name__ == "__main__":
    baetools = BaeTools()
    sys.exit(baetools.main())
